package com.osa.birthdaypie;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.graphics.Bitmap;

public class PieHighlighter implements Runnable {
	private Bitmap pie;
	private int[] buffer;
	private List<HighlightCodeHolder> pieCache;
	private List<Candle> candles;
	private volatile int[] hightlightCodeToProcess;
	
	public PieHighlighter(Bitmap pie, List<Candle> candles) {
		this.pie = pie;
		buffer = new int[pie.getHeight() * pie.getWidth()];
		pie.getPixels(buffer, 0, pie.getWidth(), 0, 0, pie.getWidth(), pie.getHeight());
		this.candles = candles;
		pieCache = Collections.synchronizedList(new ArrayList<HighlightCodeHolder>());
		Thread thread = new Thread(this);
		thread.start();
	}

	public Bitmap getPie(){
		int[] currentHighlightCode = calculateCurrentHightlightCode();
		double minDistance = Double.MAX_VALUE;
		Bitmap res = null;
		for (HighlightCodeHolder highlightCodeHolder : pieCache) {
			double distance = calculateHighlightDistance(highlightCodeHolder.code, currentHighlightCode);
			if(distance < minDistance){
				minDistance = distance;
				res = highlightCodeHolder.pie;
			}
		}
//		System.out.print("Current hightlight code: ");
//		printHightlightCode(currentHighlightCode);
		if(minDistance > 0){
			System.out.println("Pie not found in cache");
			if(res == null)
				res = pie;
			if(hightlightCodeToProcess == null){
				System.out.println("Poking worker for construction");
				hightlightCodeToProcess = currentHighlightCode;
			}
			synchronized (this) {
				System.out.println("Notifying");
				this.notify();
			}
		}
		return res;


	}
	private int[] calculateCurrentHightlightCode(){
		int[] res = new int[candles.size()];
		for (int i = 0; i < res.length; i++) {
			res[i] = candles.get(i).highlightX();
		}
		return res;
	}
	
	private double calculateHighlightDistance(int[] hightlightCode1, int[] hightlightCode2){
		double res = 0;
		for (int i = 0; i < hightlightCode1.length; i++) {
			res += Math.sqrt((hightlightCode1[i] - hightlightCode2[i]) * (hightlightCode1[i] - hightlightCode2[i]));
		}
		return res;
	}

	public void run() {
		while(true){
			System.out.println("waiting for a task");
			synchronized (this) {
				try {
					this.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			System.out.println("task obtained");
			int[] hightlightCode = hightlightCodeToProcess;
			if(hightlightCode == null)
				return;
			Bitmap hightlightedPie = hightlightPie(hightlightCode);
			pieCache.add(new HighlightCodeHolder(hightlightedPie, hightlightCode));
			System.out.println("pie cache size " + pieCache.size());
			hightlightCodeToProcess = null;
		}
	}
	
	private Bitmap hightlightPie(int[] hightlightCode){
		int[] res = new int[buffer.length];
		for(int i = 0; i < pie.getHeight(); i++){
			for(int j = 0; j < pie.getWidth(); j++){
				int color = buffer[pie.getWidth() * i + j];
				if((color & 0xFFFFFF) > 10){
					int totalHighlight = 0;
					int maxCandleHighlight = 0xF;
					for (int c = 0; c < hightlightCode.length; c++) {
						int highlightX = hightlightCode[c];
						int highlightY = candles.get(c).getY();
						int highlightRadius = 100;
						int highlightValue = highlightRadius - (int)Math.sqrt((j - highlightX) * (j - highlightX) + (i - highlightY) * (i - highlightY));
						if(highlightValue < 0)
							highlightValue = 0;
						else if(highlightValue > maxCandleHighlight){
							highlightValue = maxCandleHighlight;
						}
						totalHighlight += highlightValue;
					}
					res[pie.getWidth() * i + j] = color + 0x010101 * totalHighlight;
				}
			}
		}
		return Bitmap.createBitmap(res, 0, pie.getWidth(), pie.getWidth(), pie.getHeight(), pie.getConfig());		
	}
	private void printHightlightCode(int[] code){
		for (int i = 0; i < code.length; i++) {
			System.out.print(code[i]);
			System.out.print(", ");
		}
		System.out.println();
	}
	
	private static class HighlightCodeHolder {
		private Bitmap pie;
		private int[] code;
		public HighlightCodeHolder(Bitmap pie, int[] code) {
			this.pie = pie;
			this.code = code;
		}
	}
}
